package session.stateless.MRP.SaleForecast;

import entity.Product;
import entity.MRP.SaleForecast.AnnualSaleFigure;
import entity.MRP.SaleForecast.AnnualSaleForecast;
import entity.MRP.SaleForecast.MonthlySaleFigure;
import entity.MRP.SaleForecast.SaleFigureLineItem;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import javaclass.ProductType;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.Query;
import javax.persistence.EntityManager; 
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext; 
import session.stateless.ProductBeanLocal;

@Stateless
public class SaleFigureBean implements SaleFigureBeanLocal {

    @PersistenceContext
    private EntityManager entityManager; 
    
    @EJB
    ProductBeanLocal productBeanLocal;
    @EJB
    SaleForecastBeanLocal saleForecastBeanLocal;
    
    //get a specific sale figure
    @Override
    public MonthlySaleFigure getMonthlySaleFigure(int year, int month){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleFigure a WHERE a.saleFigureYear = :inSaleFigureYear");
        query.setParameter("inSaleFigureYear", year);
        AnnualSaleFigure annualSaleFigure = null;
        try 
        { 
            annualSaleFigure = (AnnualSaleFigure) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleFigure != null){
            return annualSaleFigure.getMonthlySaleFigures().get(month);
        }
        return null;
    }
    
    //get a list of monthly sale figure
    @Override
    public List<MonthlySaleFigure> getMonthlySaleFigures(int year, int startPeriod, int endPeriod){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleFigure a WHERE a.saleFigureYear = :inSaleFigureYear");
        query.setParameter("inSaleFigureYear", year);
        AnnualSaleFigure annualSaleFigure = null;
        try 
        { 
            annualSaleFigure = (AnnualSaleFigure) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleFigure != null){
            List<MonthlySaleFigure> monthlySaleFigures = new ArrayList<MonthlySaleFigure>();
            for (int i = startPeriod; i <= endPeriod; i++){
                monthlySaleFigures.add(annualSaleFigure.getMonthlySaleFigures().get(i));
            }
            return monthlySaleFigures;
            
        }
        return null;
    }
    
    //update a sale figure of a month after a sale order is placed successfully
    //also update the saleforecast
    @Override
    public void updateSaleFigure(int year, int month, Product product, long quantityInCases, long promotionQuantityInCases){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleFigure a WHERE a.saleFigureYear = :inSaleFigureYear");
        query.setParameter("inSaleFigureYear", year);
        AnnualSaleFigure annualSaleFigure = null;
        try 
        { 
            annualSaleFigure = (AnnualSaleFigure) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleFigure == null){
            this.generateAnnualSaleFigureBase(year);
        }
        List<SaleFigureLineItem> saleFigureLineItems = annualSaleFigure.getMonthlySaleFigures().get(month).getSaleFigureLineItems();
        AnnualSaleForecast annualSaleForecast = saleForecastBeanLocal.getAnnualSaleForecast(year + 1);
        if (annualSaleForecast == null) {
            annualSaleForecast = saleForecastBeanLocal.getAnnualSaleForecast(year + 1);
        }
        for(SaleFigureLineItem s:saleFigureLineItems){
            if (s.getProduct().equals(product)){
                s.setQuantityInCases(s.getQuantityInCases() + quantityInCases);
                s.setPromotionQuantityInCases(s.getPromotionQuantityInCases() + promotionQuantityInCases);
                saleForecastBeanLocal.updateSaleForecast(annualSaleForecast.getSaleForecastYear(), month, s.getProduct(), (long) (s.getQuantityInCases() * (100 + annualSaleForecast.getYearOverYearGrowth()) / 100), 0);
                entityManager.flush();
            }
        }
        
    }

    //method to edit sale figure mannually
    //also at the same time update the sale forecast
    @Override
    public void editSaleFigure(long monthId, List<SaleFigureLineItem> saleFigureLineItems){
        long yearId = this.findYearByMonth(monthId);
        MonthlySaleFigure monthlySaleFigure = entityManager.find(MonthlySaleFigure.class, monthId);
        AnnualSaleFigure annualSaleFigure = entityManager.find(AnnualSaleFigure.class, yearId);
        AnnualSaleForecast annualSaleForecast = saleForecastBeanLocal.getAnnualSaleForecast(annualSaleFigure.getSaleFigureYear() + 1);
        if (annualSaleForecast == null) {
            annualSaleForecast = saleForecastBeanLocal.getAnnualSaleForecast(annualSaleFigure.getSaleFigureYear() + 1);
        }
        for(SaleFigureLineItem s:monthlySaleFigure.getSaleFigureLineItems()){
            this.updateSaleFigureLineItem(s.getId(), findInListSaleFigure(s.getProduct().getProductType(), saleFigureLineItems));
            saleForecastBeanLocal.updateSaleForecast(annualSaleForecast.getSaleForecastYear(), monthlySaleFigure.getSaleFigureMonth(), s.getProduct(), (long) (s.getQuantityInCases() * (100 + annualSaleForecast.getYearOverYearGrowth()) / 100), 0);
        }
    }
    
    public void updateSaleFigureLineItem(long saleForecastLineItemId, SaleFigureLineItem saleForecastLineItem){
        SaleFigureLineItem s = entityManager.find(SaleFigureLineItem.class, saleForecastLineItemId);
        s.setQuantityInCases(saleForecastLineItem.getQuantityInCases());
        s.setPromotionQuantityInCases(saleForecastLineItem.getPromotionQuantityInCases());
        entityManager.flush();
    }
    
    public SaleFigureLineItem findInListSaleFigure(ProductType productType, List<SaleFigureLineItem> saleFigureLineItems){
        boolean check = false;
        for(SaleFigureLineItem s:saleFigureLineItems){
            if (s.getProduct().getProductType() == productType){
                return s;
            }
        }
        return null;
    }
    
    //generate a sale figure base with all quantities equal to zero
    @Override
    public void generateAnnualSaleFigureBase(int year){
        AnnualSaleFigure annualSaleFigure = new AnnualSaleFigure();
        annualSaleFigure.setSaleFigureYear(year);
        List<MonthlySaleFigure> monthlySaleFigures = new ArrayList<MonthlySaleFigure>();
        for (int i = 0; i <= 11; i++){
            MonthlySaleFigure monthlySaleFigure = new MonthlySaleFigure();
            monthlySaleFigure.setSaleFigureMonth(i);
            List<SaleFigureLineItem> saleFigureLineItems = new ArrayList<SaleFigureLineItem>();
            List<Product> productList = productBeanLocal.getProductList();
            for (Product p:productList){
                SaleFigureLineItem saleFigureLineItem = new SaleFigureLineItem();
                saleFigureLineItem.setProduct(p);
                saleFigureLineItem.setQuantityInCases((long)0);
                saleFigureLineItem.setPromotionQuantityInCases((long)0);
                saleFigureLineItems.add(saleFigureLineItem);
                entityManager.persist(saleFigureLineItem);
            }
            monthlySaleFigure.setSaleFigureLineItems(saleFigureLineItems);
            entityManager.persist(monthlySaleFigure);
            monthlySaleFigures.add(i, monthlySaleFigure);
        }
        annualSaleFigure.setMonthlySaleFigures(monthlySaleFigures);
        entityManager.persist(annualSaleFigure);
    }
    
    @Override
    public List<AnnualSaleFigure> getAnnualSaleFigures(){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleFigure a");
        List<AnnualSaleFigure> annualSaleFigures = null;
        Calendar currentDate = Calendar.getInstance();
        int currentYear = currentDate.get(Calendar.YEAR);
        try 
        { 
            annualSaleFigures = query.getResultList();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (!annualSaleFigures.isEmpty()){
            if (annualSaleFigures.get(annualSaleFigures.size() - 1).getSaleFigureYear() != currentYear){
                this.generateAnnualSaleFigureBase(currentYear);
            }
            return annualSaleFigures;
        }
        else {

            int year = 2000;
            while (year <= currentYear) {
                this.generateAnnualSaleFigureBase(year);
                year++;
            }
            return this.getAnnualSaleFigures();
        }
    }
    
    public long findYearByMonth(long monthId){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleFigure a");
        List<AnnualSaleFigure> annualSaleFigures = new ArrayList<AnnualSaleFigure>();
        try 
        { 
            annualSaleFigures = query.getResultList();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        if (annualSaleFigures.isEmpty()) return 0;
        long id = 0;
        boolean check = false;
        for (AnnualSaleFigure a:annualSaleFigures){
            for (MonthlySaleFigure m:a.getMonthlySaleFigures()){
                if (m.getId() == monthId){
                    id = a.getId();
                    check = true;
                    break;
                }
            }
            if (check) break;
        }
        return id;
    }
    
    @Override
    public AnnualSaleFigure getAnuualSaleFigure(int year){
        Query query = entityManager.createQuery("SELECT a FROM AnnualSaleFigure a WHERE a.saleFigureYear = :inSaleFigureYear");
        query.setParameter("inSaleFigureYear", year);
        AnnualSaleFigure annualSaleFigure = null;
        try 
        { 
            annualSaleFigure = (AnnualSaleFigure) query.getSingleResult();
        } 
        catch(NoResultException ex) 
        { 
            //ex.printStackTrace(); 
        } 
        return annualSaleFigure;
    }
}
